home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / tcpin.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  22KB  |  845 lines

  1. /* Process incoming TCP segments. Page number references are to ARPA RFC-793,
  2.  * the TCP specification.
  3.  */
  4.  
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "icmp.h"
  12. #include "iface.h"
  13. #include "ip.h"
  14.  
  15. struct tcp_stat tcp_stat;
  16.  
  17. /* This function is called from IP with the IP header in machine byte order,
  18.  * along with a mbuf chain pointing to the TCP header.
  19.  */
  20. void
  21. tcp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  22. struct mbuf *bp;    /* Data field, if any */
  23. char protocol;        /* Should always be TCP_PTCL */
  24. int32 source;        /* Remote IP address */
  25. int32 dest;        /* Our IP address */
  26. char tos;        /* Type of Service */
  27. int16 length;        /* Length of data field */
  28. char rxbroadcast;    /* Incoming broadcast - discard if true */
  29. {
  30.     void reset(),update();
  31.     void proc_syn(),send_syn(),add_reseq(),get_reseq(),unlink_tcb();
  32.  
  33.     register struct tcb *tcb;    /* TCP Protocol control block */
  34.     struct tcp seg;            /* Local copy of segment header */
  35.     struct connection conn;        /* Local copy of addresses */
  36.     struct pseudo_header ph;    /* Pseudo-header for checksumming */
  37.     int hdrlen;            /* Length of TCP header */
  38.  
  39.     if(bp == NULLBUF)
  40.         return;
  41.  
  42.     if(rxbroadcast){
  43.         /* Any TCP packet arriving as a broadcast is
  44.          * to be completely IGNORED!!
  45.          */
  46.         tcp_stat.bdcsts++;
  47.         free_p(bp);
  48.         return;
  49.     }
  50.     ph.source = source;
  51.     ph.dest = dest;
  52.     ph.protocol = protocol;
  53.     ph.length = length;
  54.     if(cksum(&ph,bp,length) != 0){
  55.         /* Checksum failed, ignore segment completely */
  56.         tcp_stat.checksum++;
  57.         free_p(bp);
  58.         return;
  59.     }
  60.     /* Form local copy of TCP header in host byte order */
  61.     if((hdrlen = ntohtcp(&seg,&bp)) < 0){
  62.         /* TCP header is too small */
  63.         tcp_stat.runt++;
  64.         free_p(bp);
  65.         return;
  66.     }
  67.     length -= hdrlen;
  68.  
  69.     /* Fill in connection structure and find TCB */
  70.     conn.local.address = dest;
  71.     conn.local.port = seg.dest;
  72.     conn.remote.address = source;
  73.     conn.remote.port = seg.source;
  74.     
  75.     if((tcb = lookup_tcb(&conn)) == NULLTCB){
  76.         struct tcb *ntcb;
  77.         void link_tcb();
  78.  
  79.         /* Check that this segment carries a SYN, and that
  80.          * there's a LISTEN on this socket with
  81.          * unspecified source address and port
  82.          */
  83.         conn.remote.address = 0;
  84.         conn.remote.port = 0;
  85.         if(!(seg.flags & SYN) || (tcb = lookup_tcb(&conn)) == NULLTCB){
  86.             /* No unspecified LISTEN either, so reject */
  87.             free_p(bp);
  88.             reset(source,dest,tos,length,&seg);
  89.             return;
  90.         }
  91.         /* We've found an server listen socket, so clone the TCB */
  92.         if(tcb->flags & CLONE){
  93.             if((ntcb = (struct tcb *)malloc(sizeof (struct tcb))) == NULLTCB){
  94.                 free_p(bp);
  95.                 /* This may fail, but we should at least try */
  96.                 reset(source,dest,tos,length,&seg);
  97.                 return;
  98.             }
  99.             ASSIGN(*ntcb,*tcb);
  100.             tcb = ntcb;
  101.             tcb->timer.arg = (char *)tcb;
  102.         } else
  103.             unlink_tcb(tcb);    /* It'll be put back on later */
  104.  
  105.         /* Stuff the foreign socket into the TCB */
  106.         tcb->conn.remote.address = source;
  107.         tcb->conn.remote.port = seg.source;
  108.  
  109.         /* NOW put on right hash chain */
  110.         link_tcb(tcb);
  111.     }
  112.     /* Do unsynchronized-state processing (p. 65-68) */
  113.     switch(tcb->state){
  114.     case CLOSED:
  115.         free_p(bp);
  116.         reset(source,dest,tos,length,&seg);
  117.         return;
  118.     case LISTEN:
  119.         if(seg.flags & RST){
  120.             free_p(bp);
  121.             return;
  122.         }
  123.         if(seg.flags & ACK){
  124.             free_p(bp);
  125.             reset(source,dest,tos,length,&seg);
  126.             return;
  127.         }
  128.         if(seg.flags & SYN){
  129.             /* (Security check is bypassed) */
  130.             /* page 66 */
  131.             tcp_stat.conin++;
  132.             proc_syn(tcb,tos,&seg);
  133.             send_syn(tcb);
  134.             setstate(tcb,SYN_RECEIVED);        
  135.             if(length != 0 || (seg.flags & FIN)) {
  136.                 break;        /* Continue processing if there's more */
  137.             }
  138.             tcp_output(tcb);
  139.         }
  140.         free_p(bp);    /* Unlikely to get here directly */
  141.         return;
  142.     case SYN_SENT:
  143.         if(seg.flags & ACK){
  144.             if(!seq_within(seg.ack,tcb->iss+1,tcb->snd.nxt)){
  145.                 free_p(bp);
  146.                 reset(source,dest,tos,length,&seg);
  147.                 return;
  148.             }
  149.         }
  150.         if(seg.flags & RST){    /* p 67 */
  151.             if(seg.flags & ACK){
  152.                 /* The ack must be acceptable since we just checked it.
  153.                  * This is how the remote side refuses connect requests.
  154.                  */
  155.                 close_self(tcb,RESET);
  156.             }
  157.             free_p(bp);
  158.             return;
  159.         }
  160.         /* (Security check skipped here) */
  161.         /* Check incoming precedence; it must match if there's an ACK */
  162.         if((seg.flags & ACK) && PREC(tos) != PREC(tcb->tos)){
  163.             free_p(bp);
  164.             reset(source,dest,tos,length,&seg);
  165.             return;
  166.         }
  167.         if(seg.flags & SYN){
  168.             proc_syn(tcb,tos,&seg);
  169.             if(seg.flags & ACK){
  170.                 /* Our SYN has been acked, otherwise the ACK
  171.                  * wouldn't have been valid.
  172.                  */
  173.                 update(tcb,&seg);
  174.                 setstate(tcb,ESTABLISHED);
  175.             } else {
  176.                 setstate(tcb,SYN_RECEIVED);
  177.             }
  178.             if(length != 0 || (seg.flags & FIN)) {
  179.                 break;        /* Continue processing if there's more */
  180.             }
  181.             tcp_output(tcb);
  182.         } else {
  183.             free_p(bp);    /* Ignore if neither SYN or RST is set */
  184.         }
  185.         return;
  186.     }
  187.     /* We reach this point directly in any synchronized state. Note that
  188.      * if we fell through from LISTEN or SYN_SENT processing because of a
  189.      * data-bearing SYN, window trimming and sequence testing "cannot fail".
  190.      */
  191.  
  192.     /* Trim segment to fit receive window. */
  193.     if(trim(tcb,&seg,&bp,&length) == -1){
  194.         /* Segment is unacceptable */
  195.         if(!(seg.flags & RST)){
  196.             tcb->flags |= FORCE;
  197.             tcp_output(tcb);
  198.         }
  199.         return;
  200.     }
  201.     /* If segment isn't the next one expected, and there's data
  202.      * or flags associated with it, put it on the resequencing
  203.      * queue, ACK it and return.
  204.      *
  205.      * Processing the ACK in an out-of-sequence segment without
  206.      * flags or data should be safe, however.
  207.      */
  208.     if(seg.seq != tcb->rcv.nxt
  209.      && (length != 0 || (seg.flags & (SYN|FIN)) )){
  210.         add_reseq(tcb,tos,&seg,bp,length);
  211.         tcb->flags |= FORCE;
  212.         tcp_output(tcb);
  213.         return;
  214.     }
  215.     /* This loop first processes the current segment, and then
  216.      * repeats if it can process the resequencing queue.
  217.      */
  218.     for(;;){
  219.         /* We reach this point with an acceptable segment; all data and flags
  220.          * are in the window, and the starting sequence number equals rcv.nxt
  221.          * (p. 70)
  222.          */    
  223.         if(seg.flags & RST){
  224.             if(tcb->state == SYN_RECEIVED
  225.              && !(tcb->flags & (CLONE|ACTIVE))){
  226.                 /* Go back to listen state only if this was
  227.                  * not a cloned or active server TCB
  228.                  */
  229.                 setstate(tcb,LISTEN);
  230.             } else {
  231.                 close_self(tcb,RESET);
  232.             }
  233.             free_p(bp);
  234.             return;
  235.         }
  236.         /* (Security check skipped here) p. 71 */
  237.         /* Check for precedence mismatch or erroneous extra SYN */
  238.         if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){
  239.             free_p(bp);
  240.             reset(source,dest,tos,length,&seg);
  241.             return;
  242.         }
  243.         /* Check ack field p. 72 */
  244.         if(!(seg.flags & ACK)){
  245.             free_p(bp);    /* All segments after synchronization must have ACK */
  246.             return;
  247.         }
  248.         /* Process ACK */
  249.         switch(tcb->state){
  250.         case SYN_RECEIVED:
  251.             if(seq_within(seg.ack,tcb->snd.una+1,tcb->snd.nxt)){
  252.                 update(tcb,&seg);
  253.                 setstate(tcb,ESTABLISHED);
  254.             } else {
  255.                 free_p(bp);
  256.                 reset(source,dest,tos,length,&seg);
  257.                 return;
  258.             }
  259.             break;
  260.         case ESTABLISHED:
  261.         case CLOSE_WAIT:
  262.             update(tcb,&seg);
  263.             break;
  264.         case FINWAIT1:    /* p. 73 */
  265.             update(tcb,&seg);
  266.             if(tcb->sndcnt == 0){
  267.                 /* Our FIN is acknowledged */
  268.                 setstate(tcb,FINWAIT2);
  269.             }
  270.             break;
  271.         case FINWAIT2:
  272.             update(tcb,&seg);
  273.             break;
  274.         case CLOSING:
  275.             update(tcb,&seg);
  276.             if(tcb->sndcnt == 0){
  277.                 /* Our FIN is acknowledged */
  278.                 setstate(tcb,TIME_WAIT);
  279.                 tcb->timer.start = MSL2 * (1000 / MSPTICK);
  280.                 start_timer(&tcb->timer);
  281.             }
  282.             break;
  283.         case LAST_ACK:
  284.             update(tcb,&seg);
  285.             if(tcb->sndcnt == 0){
  286.                 /* Our FIN is acknowledged, close connection */
  287.                 close_self(tcb,NORMAL);
  288.                 return;
  289.             }            
  290. /* I think this is wrong, and can cause permanent ACK-ACK loops.  dmf.
  291.         case TIME_WAIT:
  292.             tcb->flags |= FORCE;
  293.             start_timer(&tcb->timer);
  294. */
  295.         }
  296.  
  297.         /* (URGent bit processing skipped here) */
  298.  
  299.         /* Process the segment text, if any, beginning at rcv.nxt (p. 74) */
  300.         if(length != 0){
  301.             switch(tcb->state){
  302.             case SYN_RECEIVED:
  303.             case ESTABLISHED:
  304.             case FINWAIT1:
  305.             case FINWAIT2:
  306.                 /* Place on receive queue */
  307.                 append(&tcb->rcvq,bp);
  308.                 tcb->rcvcnt += length;
  309.                 tcb->rcv.nxt += length;
  310.                 tcb->rcv.wnd -= length;
  311.                 tcb->flags |= FORCE;
  312.                 break;
  313.             default:
  314.                 /* Ignore segment text */
  315.                 free_p(bp);
  316.                 break;
  317.             }
  318.         }
  319.         /* If the user has set up a r_upcall function and there's
  320.          * data to be read, notify him.
  321.          *
  322.          * This is done before sending an acknowledgement,
  323.          * to give the user a chance to piggyback some reply data.
  324.          * It's also done before processing FIN so that the state
  325.          * change upcall will occur after the user has had a chance
  326.          * to read the last of the incoming data.
  327.          */
  328.         if(tcb->r_upcall && tcb->rcvcnt != 0){
  329.             (*tcb->r_upcall)(tcb,tcb->rcvcnt);
  330.         }
  331.         /* process FIN bit (p 75) */
  332.         if(seg.flags & FIN){
  333.             tcb->flags |= FORCE;    /* Always respond with an ACK */
  334.  
  335.             switch(tcb->state){
  336.             case SYN_RECEIVED:
  337.             case ESTABLISHED:
  338.                 tcb->rcv.nxt++;
  339.                 setstate(tcb,CLOSE_WAIT);
  340.                 break;
  341.             case FINWAIT1:
  342.                 tcb->rcv.nxt++;
  343.                 if(tcb->sndcnt == 0){
  344.                     /* Our FIN has been acked; bypass CLOSING state */
  345.                     setstate(tcb,TIME_WAIT);
  346.                     tcb->timer.start = MSL2 * (1000/MSPTICK);
  347.                     start_timer(&tcb->timer);
  348.                 } else {
  349.                     setstate(tcb,CLOSING);
  350.                 }
  351.                 break;
  352.             case FINWAIT2:
  353.                 tcb->rcv.nxt++;
  354.                 setstate(tcb,TIME_WAIT);
  355.                 tcb->timer.start = MSL2 * (1000/MSPTICK);
  356.                 start_timer(&tcb->timer);
  357.                 break;
  358.             case CLOSE_WAIT:
  359.             case CLOSING:
  360.             case LAST_ACK:
  361.                 break;        /* Ignore */
  362.             case TIME_WAIT:    /* p 76 */
  363.                 start_timer(&tcb->timer);
  364.                 break;
  365.             }
  366.         }
  367.         /* Scan the resequencing queue, looking for a segment we can handle,
  368.          * and freeing all those that are now obsolete.
  369.          */
  370.         while(tcb->reseq != NULLRESEQ && seq_ge(tcb->rcv.nxt,tcb->reseq->seg.seq)){
  371.             get_reseq(tcb,&tos,&seg,&bp,&length);
  372.             if(trim(tcb,&seg,&bp,&length) == 0)
  373.                 goto gotone;
  374.             /* Segment is an old one; trim has freed it */
  375.         }
  376.         break;
  377. gotone:    ;
  378.     }
  379.     tcp_output(tcb);    /* Send any necessary ack */
  380. }
  381.  
  382. /* Process an incoming ICMP response */
  383. tcp_icmp(source,dest,type,code,bpp)
  384. int32 source;            /* Original IP datagram source (i.e. us) */
  385. int32 dest;            /* Original IP datagram dest (i.e., them) */
  386. char type,code;            /* ICMP error codes */
  387. struct mbuf **bpp;        /* First 8 bytes of TCP header */
  388. {
  389.     struct tcp seg;
  390.     struct connection conn;
  391.     register struct tcb *tcb;
  392.  
  393.     /* Extract the socket info from the returned TCP header fragment
  394.      * Note that since this is a datagram we sent, the source fields
  395.      * refer to the local side.
  396.      */
  397.     ntohtcp(&seg,bpp);
  398.     conn.local.port = seg.source;
  399.     conn.remote.port = seg.dest;
  400.     conn.local.address = source;
  401.     conn.remote.address = dest;
  402.     if((tcb = lookup_tcb(&conn)) == NULLTCB)
  403.         return;    /* Unknown connection, ignore */
  404.  
  405.     /* Verify that the sequence number in the returned segment corresponds
  406.      * to something currently unacknowledged. If not, it can safely
  407.      * be ignored.
  408.      */
  409.     if(!seq_within(seg.seq,tcb->snd.una,tcb->snd.nxt))
  410.         return;
  411.  
  412.     /* The strategy here is that Destination Unreachable and Time Exceeded
  413.      * messages that occur after a connection has been established are likely
  414.      * to be transient events, and shouldn't kill our connection (at least
  415.      * until after we've tried a few more times). On the other hand, if
  416.      * they occur on our very first attempt to send a datagram on a new
  417.      * connection, they're probably "for real". In any event, the info
  418.      * is saved.
  419.      */
  420.     switch(uchar(type)){
  421.     case DEST_UNREACH:
  422.     case TIME_EXCEED:
  423.         tcb->type = type;
  424.         tcb->code = code;
  425.         if(tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED){
  426.             close_self(tcb,NETWORK);
  427.         }
  428.         break;
  429.     case QUENCH:
  430.         /* Source quench; cut the congestion window in half,
  431.          * but don't let it go below one packet
  432.          */
  433.         tcb->cwind /= 2;
  434.         tcb->cwind = max(tcb->mss,tcb->cwind);
  435.         break;
  436.     }
  437. }
  438. /* Send an acceptable reset (RST) response for this segment
  439.  * The RST reply is composed in place on the input segment
  440.  */
  441. static void
  442. reset(source,dest,tos,length,seg)
  443. int32 source;            /* Remote IP address */
  444. int32 dest;            /* Our IP address */
  445. char tos;            /* Type of Service */
  446. int16 length;            /* Length of data portion */
  447. register struct tcp *seg;    /* Offending TCP header */
  448. {
  449.     struct mbuf *hbp;
  450.     struct pseudo_header ph;
  451.     int16 tmp;
  452.     char rflags;
  453.  
  454.     if(seg->flags & RST)
  455.         return;    /* Never send an RST in response to an RST */
  456.  
  457.     tcp_stat.resets++;
  458.  
  459.     /* Compose the RST IP pseudo-header, swapping addresses */
  460.     ph.source = dest;
  461.     ph.dest = source;
  462.     ph.protocol = TCP_PTCL;
  463.     ph.length = TCPLEN;
  464.  
  465.     /* Swap port numbers */
  466.     tmp = seg->dest;
  467.     seg->dest = seg->source;
  468.     seg->source = tmp;
  469.  
  470.     rflags = RST;
  471.     if(seg->flags & ACK){
  472.         /* This reset is being sent to clear a half-open connection.
  473.          * Set the sequence number of the RST to the incoming ACK
  474.          * so it will be acceptable.
  475.          */
  476.         seg->seq = seg->ack;
  477.         seg->ack = 0;
  478.     } else {
  479.         /* We're rejecting a connect request (SYN) from LISTEN state
  480.          * so we have to "acknowledge" their SYN.
  481.          */
  482.         rflags |= ACK;
  483.         seg->ack = seg->seq;
  484.         seg->seq = 0;
  485.         if(seg->flags & SYN)
  486.             seg->ack++;
  487.         seg->ack += length;
  488.         if(seg->flags & FIN)
  489.             seg->ack++;
  490.     }
  491.     seg->flags = rflags;
  492.     seg->wnd = 0;
  493.     seg->up = 0;
  494.     seg->mss = 0;
  495.     if((hbp = htontcp(seg,NULLBUF,&ph)) == NULLBUF)
  496.         return;
  497.     /* Ship it out (note swap of addresses) */
  498.     ip_send(dest,source,TCP_PTCL,tos,0,hbp,ph.length,0,0);
  499. }
  500.  
  501. /* Process an incoming acknowledgement and window indication.
  502.  * From page 72.
  503.  */
  504. static void
  505. update(tcb,seg)
  506. register struct tcb *tcb;
  507. register struct tcp *seg;
  508. {
  509.     int16 acked;
  510.     int16 expand;
  511.  
  512.     acked = 0;
  513.     if(seq_gt(seg->ack,tcb->snd.nxt)){
  514.         tcb->flags |= FORCE;    /* Acks something not yet sent */
  515.         return;
  516.     }
  517.     /* Decide if we need to do a window update.
  518.      * This is always checked whenever a legal ACK is received,
  519.      * even if it doesn't actually acknowledge anything,
  520.      * because it might be a spontaneous window reopening.
  521.      */
  522.     if(seq_gt(seg->seq,tcb->snd.wl1) || ((seg->seq == tcb->snd.wl1) 
  523.      && seq_ge(seg->ack,tcb->snd.wl2))){
  524.         /* If the window had been closed, crank back the
  525.          * send pointer so we'll immediately resume transmission.
  526.          * Otherwise we'd have to wait until the next probe.
  527.          */
  528.         if(tcb->snd.wnd == 0 && seg->wnd != 0)
  529.             tcb->snd.ptr = tcb->snd.una;
  530.         tcb->snd.wnd = seg->wnd;
  531.         tcb->snd.wl1 = seg->seq;
  532.         tcb->snd.wl2 = seg->ack;
  533.     }
  534.     /* See if anything new is being acknowledged */
  535.     if(!seq_gt(seg->ack,tcb->snd.una))
  536.         return;    /* Nothing more to do */
  537.  
  538.     /* We're here, so the ACK must have actually acked something */
  539.     acked = seg->ack - tcb->snd.una;
  540.  
  541.     /* Expand congestion window if not already at limit */
  542.     if(tcb->cwind < tcb->snd.wnd){
  543.         if(tcb->cwind < tcb->ssthresh){
  544.             /* Still doing slow start/CUTE, expand by amount acked */
  545.             expand = min(acked,tcb->mss);
  546.         } else {
  547.             /* Steady-state test of extra path capacity */
  548.             expand = ((long)tcb->mss * tcb->mss) / tcb->cwind;
  549.         }
  550.         /* Guard against arithmetic overflow */
  551.         if(tcb->cwind + expand < tcb->cwind)
  552.             expand = MAXINT16 - tcb->cwind;
  553.  
  554.         /* Don't expand beyond the offered window */
  555.         if(tcb->cwind + expand > tcb->snd.wnd)
  556.             expand = tcb->snd.wnd - tcb->cwind;
  557.  
  558.         if(expand != 0){
  559. #ifdef    notdef
  560.             /* Kick up the mean deviation estimate to prevent
  561.              * unnecessary retransmission should we already be
  562.              * bandwidth limited
  563.              */
  564.             tcb->mdev += ((long)tcb->srtt * expand) / tcb->cwind;
  565. #endif
  566.             tcb->cwind += expand;
  567.         }
  568.     }
  569.     /* Round trip time estimation */
  570.     if(run_timer(&tcb->rtt_timer) && seq_ge(seg->ack,tcb->rttseq)){
  571.         /* A timed sequence number has been acked */
  572.         stop_timer(&tcb->rtt_timer);
  573.         if(!(tcb->flags & RETRAN)){
  574.             int32 rtt;    /* measured round trip time */
  575.             int32 abserr;    /* abs(rtt - srtt) */
  576.  
  577.             /* This packet was sent only once and now
  578.              * it's been acked, so process the round trip time
  579.              */
  580.             rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
  581.             rtt *= MSPTICK;        /* milliseconds */
  582.  
  583.             /* If this ACKs our SYN, this is the first ACK
  584.              * we've received; base our entire SRTT estimate
  585.              * on it. Otherwise average it in with the prior
  586.              * history, also computing mean deviation.
  587.              */
  588.             if(rtt > tcb->srtt &&
  589.              (tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED)){
  590.                 tcb->srtt = rtt;
  591.             } else {
  592.                 abserr = (rtt > tcb->srtt) ? rtt - tcb->srtt : tcb->srtt - rtt;
  593.                 tcb->srtt = ((AGAIN-1)*tcb->srtt + rtt) / AGAIN;
  594.                 tcb->mdev = ((DGAIN-1)*tcb->mdev + abserr) / DGAIN;
  595.             }
  596.             /* Reset the backoff level */
  597.             tcb->backoff = 0;
  598.         }
  599.     }
  600.     /* If we're waiting for an ack of our SYN, note it and adjust count */
  601.     if(!(tcb->flags & SYNACK)){
  602.         tcb->flags |= SYNACK;
  603.         acked--;
  604.         tcb->sndcnt--;
  605.     }
  606.     /* Remove acknowledged bytes from the send queue and update the
  607.      * unacknowledged pointer. If a FIN is being acked,
  608.      * pullup won't be able to remove it from the queue.
  609.      */
  610.     pullup(&tcb->sndq,NULLCHAR,acked);
  611.  
  612.     /* This will include the FIN if there is one */
  613.     tcb->sndcnt -= acked;
  614.     tcb->snd.una = seg->ack;
  615.  
  616.     /* Stop retransmission timer, but restart it if there is still
  617.      * unacknowledged data.
  618.      */    
  619.     stop_timer(&tcb->timer);
  620.     if(tcb->snd.una != tcb->snd.nxt)
  621.         start_timer(&tcb->timer);
  622.  
  623.     /* If retransmissions have been occurring, make sure the
  624.      * send pointer doesn't repeat ancient history
  625.      */
  626.     if(seq_lt(tcb->snd.ptr,tcb->snd.una))
  627.         tcb->snd.ptr = tcb->snd.una;
  628.  
  629.     /* Clear the retransmission flag since the oldest
  630.      * unacknowledged segment (the only one that is ever retransmitted)
  631.      * has now been acked.
  632.      */
  633.     tcb->flags &= ~RETRAN;
  634.  
  635.     /* If outgoing data was acked, notify the user so he can send more
  636.      * unless we've already sent a FIN.
  637.      */
  638.     if(acked != 0 && tcb->t_upcall){
  639.         switch(tcb->state){
  640.          case ESTABLISHED:
  641.         case CLOSE_WAIT:
  642.             (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  643.         }
  644.     }
  645. }
  646.  
  647. /* Determine if the given sequence number is in our receiver window.
  648.  * NB: must not be used when window is closed!
  649.  */
  650. static
  651. int
  652. in_window(tcb,seq)
  653. struct tcb *tcb;
  654. int32 seq;
  655. {
  656.     return seq_within(seq,tcb->rcv.nxt,(int32)(tcb->rcv.nxt+tcb->rcv.wnd-1));
  657. }
  658.  
  659. /* Process an incoming SYN */
  660. static void
  661. proc_syn(tcb,tos,seg)
  662. register struct tcb *tcb;
  663. char tos;
  664. struct tcp *seg;
  665. {
  666.     int16 mtu,ip_mtu();
  667.  
  668.     tcb->flags |= FORCE;    /* Always send a response */
  669.  
  670.     /* Note: It's not specified in RFC 793, but SND.WL1 and
  671.      * SND.WND are initialized here since it's possible for the
  672.      * window update routine in update() to fail depending on the
  673.      * IRS if they are left unitialized.
  674.      */
  675.     /* Check incoming precedence and increase if higher */
  676.     if(PREC(tos) > PREC(tcb->tos))
  677.         tcb->tos = tos;
  678.     tcb->rcv.nxt = seg->seq + 1;    /* p 68 */
  679.     tcb->snd.wl1 = tcb->irs = seg->seq;
  680.     tcb->snd.wnd = seg->wnd;
  681.     if(seg->mss != 0)
  682.         tcb->mss = seg->mss;
  683.     /* Check the MTU of the interface we'll use to reach this guy
  684.      * and lower the MSS so that unnecessary fragmentation won't occur
  685.      */
  686.     if((mtu = ip_mtu(tcb->conn.remote.address)) != 0){
  687.         /* Allow space for the TCP and IP headers */
  688.         mtu -= TCPLEN + IPLEN;
  689.         tcb->cwind = tcb->mss = min(mtu,tcb->mss);
  690.     }
  691. }
  692.  
  693. /* Generate an initial sequence number and put a SYN on the send queue */
  694. void
  695. send_syn(tcb)
  696. register struct tcb *tcb;
  697. {
  698.     tcb->iss = iss();
  699.     tcb->rttseq = tcb->snd.wl2 = tcb->snd.una = tcb->iss;
  700.     tcb->snd.ptr = tcb->snd.nxt = tcb->rttseq;
  701.     tcb->sndcnt++;
  702.     tcb->flags |= FORCE;
  703. }
  704.  
  705. /* Add an entry to the resequencing queue in the proper place */
  706. static void
  707. add_reseq(tcb,tos,seg,bp,length)
  708. struct tcb *tcb;
  709. char tos;
  710. struct tcp *seg;
  711. struct mbuf *bp;
  712. int16 length;
  713. {
  714.     register struct reseq *rp,*rp1;
  715.  
  716.     /* Allocate reassembly descriptor */
  717.     if((rp = (struct reseq *)malloc(sizeof (struct reseq))) == NULLRESEQ){
  718.         /* No space, toss on floor */
  719.         free_p(bp);
  720.         return;
  721.     }
  722.     ASSIGN(rp->seg,*seg);
  723.     rp->tos = tos;
  724.     rp->bp = bp;
  725.     rp->length = length;
  726.  
  727.     /* Place on reassembly list sorting by starting seq number */
  728.     rp1 = tcb->reseq;
  729.     if(rp1 == NULLRESEQ || seq_lt(seg->seq,rp1->seg.seq)){
  730.         /* Either the list is empty, or we're less than all other
  731.          * entries; insert at beginning.
  732.          */
  733.         rp->next = rp1;
  734.         tcb->reseq = rp;
  735.     } else {
  736.         /* Find the last entry less than us */
  737.         for(;;){
  738.             if(rp1->next == NULLRESEQ || seq_lt(seg->seq,rp1->next->seg.seq)){
  739.                 /* We belong just after this one */
  740.                 rp->next = rp1->next;
  741.                 rp1->next = rp;
  742.                 break;
  743.             }
  744.             rp1 = rp1->next;
  745.         }
  746.     }
  747. }
  748.  
  749. /* Fetch the first entry off the resequencing queue */
  750. static void
  751. get_reseq(tcb,tos,seg,bp,length)
  752. register struct tcb *tcb;
  753. char *tos;
  754. struct tcp *seg;
  755. struct mbuf **bp;
  756. int16 *length;
  757. {
  758.     register struct reseq *rp;
  759.  
  760.     if((rp = tcb->reseq) == NULLRESEQ)
  761.         return;
  762.  
  763.     tcb->reseq = rp->next;
  764.  
  765.     *tos = rp->tos;
  766.     ASSIGN(*seg,rp->seg);
  767.     *bp = rp->bp;
  768.     *length = rp->length;
  769.     free((char *)rp);
  770. }
  771.  
  772. /* Trim segment to fit window. Return 0 if OK, -1 if segment is
  773.  * unacceptable.
  774.  */
  775. static int
  776. trim(tcb,seg,bp,length)
  777. register struct tcb *tcb;
  778. register struct tcp *seg;
  779. struct mbuf **bp;
  780. int16 *length;
  781. {
  782.     struct mbuf *nbp;
  783.     long dupcnt,excess;
  784.     int16 len;        /* Segment length including flags */
  785.     char accept;
  786.  
  787.     accept = 0;
  788.     len = *length;
  789.     if(seg->flags & SYN)
  790.         len++;
  791.     if(seg->flags & FIN)
  792.         len++;
  793.  
  794.     /* Acceptability tests */
  795.     if(tcb->rcv.wnd == 0){
  796.         /* Only in-order, zero-length segments are acceptable when our window
  797.          * is closed.
  798.          */
  799.         if(seg->seq == tcb->rcv.nxt && len == 0){
  800.             return 0;    /* Acceptable, no trimming needed */
  801.         }
  802.     } else {
  803.         /* Some part of the segment must be in the window */
  804.         if(in_window(tcb,seg->seq)){
  805.             accept++;    /* Beginning is */
  806.         } else if(len != 0){
  807.             if(in_window(tcb,(int32)(seg->seq+len-1)) || /* End is */
  808.              seq_within(tcb->rcv.nxt,seg->seq,(int32)(seg->seq+len-1))){ /* Straddles */
  809.                 accept++;
  810.             }
  811.         }
  812.     }
  813.     if(!accept){
  814.         free_p(*bp);
  815.         return -1;
  816.     }
  817.     dupcnt = tcb->rcv.nxt - seg->seq;
  818.     if(dupcnt > 0){
  819.         tcb->rerecv += dupcnt;
  820.         /* Trim off SYN if present */
  821.         if(seg->flags & SYN){
  822.             /* SYN is before first data byte */
  823.             seg->flags &= ~SYN;
  824.             seg->seq++;
  825.             dupcnt--;
  826.         }
  827.         if(dupcnt > 0){
  828.             pullup(bp,NULLCHAR,(int16)dupcnt);
  829.             seg->seq += dupcnt;
  830.             *length -= dupcnt;
  831.         }
  832.     }
  833.     excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
  834.     if(excess > 0){
  835.         tcb->rerecv += excess;
  836.         /* Trim right edge */
  837.         *length -= excess;
  838.         nbp = copy_p(*bp,*length);
  839.         free_p(*bp);
  840.         *bp = nbp;
  841.         seg->flags &= ~FIN;    /* FIN follows last data byte */
  842.     }
  843.     return 0;
  844. }
  845.